Raspberry PiとAWSを繋いでみる ~MQTT のデモ~
こんにちは。CX事業本部のKyoです。引き続きラズパイとAWS IoT Coreを触っていきます。
前回はこちら。
概要
前回AWS IoT Device Clientをセットアップしたラズパイにより詳細な設定を行い、MQTTでIoT Coreと双方向で通信します。
具体的には以下の手順を行います。
AWS IoT Device Client との MQTT メッセージ通信をデモンストレーションする
ステップ 1: Raspberry Pi を準備して MQTT メッセージ通信のデモンストレーションをする
このステップは前回とほぼ同じ内容でした。ラズパイへの証明書セットアップ、AWS IoTへのプロビジョニング、MQTT テストクライアントでのサブスクライブの準備、を行いました。
違いがあるとすれば、1つのデバイスに対して複数の証明書をセットアップした点です。本文にも以下のような表現がありました。
AWS IoT のモノのリソースはクラウド内のデバイスの仮想表現なので、AWS IoT に複数のモノのリソースを作成して、さまざまな目的で使用できます。これらすべてを同じ物理 IoT デバイスで使用して、デバイスのさまざまな側面を表すことができます。
また、AWS IoTポリシーの書き方もより限定的になっていました。
前回
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iot:Publish", "iot:Subscribe", "iot:Receive", "iot:Connect" ], "Resource": [ "*" ] } ] }
今回
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iot:Connect" ], "Resource": [ "arn:aws:iot:<リージョン>:<アカウントID>:client/PubSubTestThing" ] }, { "Effect": "Allow", "Action": [ "iot:Publish" ], "Resource": [ "arn:aws:iot:<リージョン>:<アカウントID>:topic/test/dc/pubtopic" ] }, { "Effect": "Allow", "Action": [ "iot:Subscribe" ], "Resource": [ "arn:aws:iot:<リージョン>:<アカウントID>:topicfilter/test/dc/subtopic" ] }, { "Effect": "Allow", "Action": [ "iot:Receive" ], "Resource": [ "arn:aws:iot:<リージョン>:<アカウントID>:topic/test/dc/subtopic" ] } ] }
ステップ 2: AWS IoT Device Client でのメッセージの発行をデモンストレーションする
AWS IoT Device Client を使用してデフォルトメッセージを発行する
まず、AWS IoT Device Client を使用してデフォルトメッセージを発行します。無事にHello Worldできています。ここまでが前回と同じ部分です。
AWS IoT Device Client を使用してカスタムメッセージを発行する
カスタムメッセージを発行していきます。まずはラズパイ側で以下のJSONファイルを作成します。これがカスタムメッセージのペイロードになります。
{ "temperature": 28, "humidity": 80, "barometer": 1013, "wind": { "velocity": 22, "bearing": 255 } }
その後、デフォルトメッセージの設定ファイルを元に以下のような設定ファイルを作成します。作成したペイロードJSONのパスが含まれている点がポイントです。
{ "endpoint": "<デバイスデータエンドポイント>", "cert": "~/certs/pubsub/device.pem.crt", "key": "~/certs/pubsub/private.pem.key", "root-ca": "~/certs/AmazonRootCA1.pem", "thing-name": "PubSubTestThing", "logging": { "enable-sdk-logging": true, "level": "DEBUG", "type": "STDOUT", "file": "" }, "jobs": { "enabled": false, "handler-directory": "" }, "tunneling": { "enabled": false }, "device-defender": { "enabled": false, "interval": 300 }, "fleet-provisioning": { "enabled": false, "template-name": "", "template-parameters": "", "csr-file": "", "device-key": "" }, "samples": { "pub-sub": { "enabled": true, "publish-topic": "test/dc/pubtopic", "publish-file": "<ペイロードファイルのパス>", "subscribe-topic": "test/dc/subtopic", "subscribe-file": "~/.aws-iot-device-client/log/pubsub_rx_msgs.log" } }, "config-shadow": { "enabled": false }, "sample-shadow": { "enabled": false, "shadow-name": "", "shadow-input-file": "", "shadow-output-file": "" } }
両ファイルに適切なパーミッションが設定されていることを確認したら、以下のコマンドでカスタムメッセージを発行します。
./aws-iot-device-client --config-file ~/dc-configs/dc-pubsub-custom-config.json
テストクライアントでは以下のように受信できました。
ステップ 3: AWS IoT Device Client でメッセージのサブスクリプションをデモンストレーションする
単一の MQTT メッセージトピックをサブスクライブする
改めて先ほどの設定JSONを確認します。
subscribe-topic
が test/dc/subtopic
に設定されていますね。これはtest/dc/subtopic
というトピックを(ラズパイ側で)サブスクライブできることを示しています。
また、このサブスクリプションから受信したペイロードはsubscribe-file
で指定されている~/.aws-iot-device-client/log/pubsub_rx_msgs.log
に書き込まれることになります。
"samples": { "pub-sub": { "enabled": true, "publish-topic": "test/dc/pubtopic", "publish-file": "", "subscribe-topic": "test/dc/subtopic", "subscribe-file": "~/.aws-iot-device-client/log/pubsub_rx_msgs.log" } }, ...
AWS IoT Device Clientを実行し、テストクライアントからtest/dc/subtopic
というトピック名のメッセージを発行します。
ラズパイのターミナルには以下のように表示されました。
2023-03-29T14:42:44.059Z [DEBUG] {samples/PubSubFeature.cpp}: Message received on subscribe topic, size: 57 bytes
また、書き込み先にはペイロードが書き込まれていることが確認できました。
$ tail ~/.aws-iot-device-client/log/pubsub_rx_msgs.log { "message": "AWS IoT コンソールからの挨拶" }
なお、トピック名をtest/dc/subtopic2
に変えるとメッセージの受信・ログへの書き込み共に行われないことも確認できました。
ワイルドカード文字を使用して複数の MQTT メッセージトピックをサブスクライブする
これまでの設定JSONを元に新しい設定JSONを作成します。subscribe-topic
がtest/dc/#
になっています。この#
がワイルドカードを意味します。
{ "endpoint": "", "cert": "~/certs/pubsub/device.pem.crt", "key": "~/certs/pubsub/private.pem.key", "root-ca": "~/certs/AmazonRootCA1.pem", "thing-name": "PubSubTestThing", "logging": { "enable-sdk-logging": true, "level": "DEBUG", "type": "STDOUT", "file": "" }, "jobs": { "enabled": false, "handler-directory": "" }, "tunneling": { "enabled": false }, "device-defender": { "enabled": false, "interval": 300 }, "fleet-provisioning": { "enabled": false, "template-name": "", "template-parameters": "", "csr-file": "", "device-key": "" }, "samples": { "pub-sub": { "enabled": true, "publish-topic": "test/dc/pubtopic", "publish-file": "", "subscribe-topic": "test/dc/#", "subscribe-file": "~/.aws-iot-device-client/log/pubsub_rx_msgs.log" } }, "config-shadow": { "enabled": false }, "sample-shadow": { "enabled": false, "shadow-name": "", "shadow-input-file": "", "shadow-output-file": "" } }
AWS IoT ポリシーの変更も必要です。iot::Subscribe
とiot::Receive
のResource
をワイルドカードを含む形に書き換えます。ポリシーでのワイルドカードは#
でないことに気をつけます。
{ "Effect": "Allow", "Action": [ "iot:Subscribe" ], "Resource": [ "arn:aws:iot:<リージョン>:<アカウントID>:topicfilter/test/dc/*" ] }, { "Effect": "Allow", "Action": [ "iot:Receive" ], "Resource": [ "arn:aws:iot:<リージョン>:<アカウントID>:topicfilter/test/dc/*" ] }
更新後のポリシーです。バージョンが2
になってます。
テストクライアントで#
をサブスクライブします。また、ラズパイ側でもAWS IoT Device Clientを起動しておきます。
テストクライアントから二種類トピックを発行します。はじめにtest/dc/subtopic
、次に(先ほどの設定ではサブスクライブできなかった)test/dc/subtopic2
を発行します。
ラズパイ側では以下のようなログが表示されていました。
2023-03-29T15:03:35.493Z [DEBUG] {samples/PubSubFeature.cpp}: Message received on subscribe topic, size: 119 bytes 2023-03-29T15:04:06.148Z [DEBUG] {samples/PubSubFeature.cpp}: Message received on subscribe topic, size: 58 bytes
ログファイルも同様です。
tail -n 20 ~/.aws-iot-device-client/log/pubsub_rx_msgs.log { "message": "AWS IoT コンソールからの挨拶" }{ "temperature": 28, "humidity": 80, "barometer": 1013, "wind": { "velocity": 22, "bearing": 255 } } { "message": "AWS IoT コンソールからの挨拶2"
…よく見ると3件入っていますね。これについては以下の説明がありました。
受信したログには AWS IoT Device Client によって発行されたメッセージが表示されることもあります。これは、ワイルドカードトピックフィルターにそのメッセージトピックが含まれており、発行されたメッセージがサブスクライバーに送信される前にメッセージブローカーがサブスクリプションリクエストを処理することがあるためです。
おわりに
今回は前回の復習をしつつ、より詳しくMQTTの扱いを体験しました。 サブスクライブできるトピックはAWS IoT Device Clientの設定による制御とAWS IoT ポリシーによる制御が行われており、それぞれでワイルドカードも利用できる、というのがポイントでしょうか。